/* * Copyright (C) 2009 University of Washington * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.commcare.android.tasks; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; import java.util.Date; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.entity.mime.MIME; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.StringBody; import org.commcare.android.database.user.models.User; import org.commcare.android.javarosa.AndroidLogEntry; import org.commcare.android.javarosa.AndroidLogSerializer; import org.commcare.android.javarosa.DeviceReportWriter; import org.commcare.android.net.HttpRequestGenerator; import org.commcare.dalvik.R; import org.commcare.dalvik.application.CommCareApplication; import android.content.SharedPreferences; import android.os.AsyncTask; /** * Background task for uploading completed forms. * * @author csims@dimagi.com * **/ public class ExceptionReportTask extends AsyncTask<Throwable, String, String> { /* * (non-Javadoc) * @see android.os.AsyncTask#doInBackground(java.lang.Object[]) */ @Override protected String doInBackground(Throwable... values) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); //TODO: This is ridiculous. Just do the normal log submission process DeviceReportWriter report; try{ report = new DeviceReportWriter(baos); } catch(IOException e){ report = null; } String fallbacktext = null; for(Throwable ex : values) { String exceptionText = getStackTrace(ex); if(fallbacktext == null) { fallbacktext = exceptionText; } if(report != null) { report.addReportElement(new AndroidLogSerializer(new AndroidLogEntry("forceclose", exceptionText, new Date()))); } } byte[] data; try { if(report == null) { throw new IOException();} report.write(); data = baos.toByteArray(); } catch (IOException e) { //_weak_ e.printStackTrace(); String fsDate = new Date().toString(); data = ("<?xml version='1.0' ?><n0:device_report xmlns:n0=\"http://code.javarosa.org/devicereport\"><device_id>FAILSAFE</device_id><report_date>" + fsDate +"</report_date><log_subreport><log_entry date=\"" + fsDate + "\"><entry_type>forceclose</entry_type><entry_message>" + fallbacktext + "</entry_message></log_entry></log_subreport></device_report>").getBytes(); } String URI = CommCareApplication._().getString(R.string.PostURL); try { SharedPreferences settings = CommCareApplication._().getCurrentApp().getAppPreferences(); URI = settings.getString("PostURL", CommCareApplication._().getString(R.string.PostURL)); } catch(Exception e) { //D-oh. Really? } //TODO: Send this with the standard logging subsystem String payload = new String(data); System.out.println("Outgoing payload: " + payload); MultipartEntity entity = new MultipartEntity(); try { //Apparently if you don't have a filename in the multipart wrapper, some receivers //don't properly receive this post. StringBody body = new StringBody(payload, "text/xml", MIME.DEFAULT_CHARSET) { /* * (non-Javadoc) * @see org.apache.http.entity.mime.content.StringBody#getFilename() */ @Override public String getFilename() { return "exceptionreport.xml"; } }; entity.addPart("xml_submission_file", body); } catch (IllegalCharsetNameException e1) { e1.printStackTrace(); } catch (UnsupportedCharsetException e1) { e1.printStackTrace(); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } HttpRequestGenerator generator; try { User user = CommCareApplication._().getSession().getLoggedInUser(); if(user.getUserType().equals(User.TYPE_DEMO)) { generator = new HttpRequestGenerator(); } else { generator = new HttpRequestGenerator(user); } } catch(Exception e){ generator = new HttpRequestGenerator(); } try { HttpResponse response = generator.postData(URI, entity); ByteArrayOutputStream bos = new ByteArrayOutputStream(); response.getEntity().writeTo(bos); System.out.println("Response: " + new String(bos.toByteArray())); } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } //We seem to have to return something... return null; } public static String getStackTrace(Throwable e) { return getStackTrace(e, false); } public static String getStackTrace(Throwable e, boolean fullContext) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); e.printStackTrace(new PrintStream(bos)); String retString = new String(bos.toByteArray()); if(fullContext && e.getCause() != null) { //Because sometimes it doesn't print us enough context. retString += "Sub Context: \n" + getStackTrace(e.getCause(), false); } return retString; } }